#ifndef __WIZ_DATATYPE_OPTIONAL_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_OPTIONAL_HPP__SHANHAOBO_19800429__

#include "../Base/WizBase.hpp"

namespace Wiz
{
    namespace Optional
    {
        template <class StorageT>
        class Type : public ::Wiz::Operators::ComparableAll::Type<::Wiz::Optional::Type<StorageT>, StorageT, ::Wiz::Null::Type>
        {
        public:
            WIZ_DECLARE_CLASS_THIS(Type);
            typedef StorageT    tStorage;
        private:
            tStorage m_Value;
            ::Wiz::Bool::Type m_Valid;
        public:
            Type() : m_Valid(::Wiz::Bool::False)
            {
            }
            Type(tStorage const& Val) : m_Value(Val), m_Valid(::Wiz::Bool::True)
            {
            }
            Type(tStorage const& Val, ::Wiz::Bool::In B) : m_Value(Val), m_Valid(B)
            {
            }
            ~Type()
            {
                Destroy();
            }
        public:
            WIZ_INLINE friend ::Wiz::Bool::Type operator==(tThisIn X, const tStorage& Y)
            {
                if (X.m_Valid == ::Wiz::Bool::False)
                {
                    return ::Wiz::Bool::False;
                }
                return X.m_Value == Y;
            }
            WIZ_INLINE friend ::Wiz::Bool::Type operator==(tThisIn X, tThisIn Y)
            {
                if ((X.m_Valid == ::Wiz::Bool::False) || (Y.m_Valid == ::Wiz::Bool::False))
                {
                    return ::Wiz::Bool::False;
                }
                return X.m_Value == Y.m_Value;
            }
            WIZ_INLINE friend ::Wiz::Bool::Type operator<(tThisIn X, const tStorage& Y)
            {
                if (X.m_Valid == ::Wiz::Bool::False)
                {
                    return ::Wiz::Bool::False;
                }
                return X.m_Value < Y;
            }
            WIZ_INLINE friend ::Wiz::Bool::Type operator>(tThisIn X, const tStorage& Y)
            {
                if (X.m_Valid == ::Wiz::Bool::False)
                {
                    return ::Wiz::Bool::False;
                }
                return X.m_Value > Y;
            }
            WIZ_INLINE friend ::Wiz::Bool::Type operator<(tThisIn X, tThisIn Y)
            {
                if ((X.m_Valid == ::Wiz::Bool::False) || (Y.m_Valid == ::Wiz::Bool::False))
                {
                    return ::Wiz::Bool::False;
                }
                return X.m_Value < Y.m_Value;
            }
        public:
            tThisIn operator=(tThisIn Other)
            {
                if (Other.IsValid())
                {
                    this->m_Value = Other.m_Value;
                    this->m_Valid = ::Wiz::Bool::True;
                }

                return Other;
            }
        public:
            ::Wiz::Void::Type Reset()
            {
                Destroy();
            }
            ::Wiz::Void::Type Reset(tStorage const& SV)
            {
                m_Value = SV;
                m_Valid = ::Wiz::Bool::True;
            }
        public:
            ::Wiz::Bool::Type IsValid() const
            {
                return m_Valid;
            }
            ::Wiz::Bool::Type NotValid() const
            {
                return m_Valid == ::Wiz::Bool::False;;
            }
            tStorage const& Get() const
            {
                WIZ_ASSERT(m_Valid);
                return m_Value;
            }
            tStorage const& GetOr(tStorage& Def) const
            {
                if (m_Valid)
                {
                    return m_Value;
                }
                return Def;
            }
            ::Wiz::Void::Type Destroy()
            {
                m_Valid = ::Wiz::Bool::False;
            }
        public:
        };
    } /// end of namespace Optional
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_OPTIONAL_HPP__SHANHAOBO_19800429__*/
